Skip to content

[feat: heft-oxlint-plugin] Add oxlint plugin integration to heft#5887

Open
yashwanth195 wants to merge 2 commits into
microsoft:mainfrom
yashwanth195:oxlint
Open

[feat: heft-oxlint-plugin] Add oxlint plugin integration to heft#5887
yashwanth195 wants to merge 2 commits into
microsoft:mainfrom
yashwanth195:oxlint

Conversation

@yashwanth195

Copy link
Copy Markdown
Contributor

rushstack-heft-oxlint-plugin

Adds a new Heft task plugin that runs oxlint, the Rust-based JavaScript/TypeScript linter from the Oxc project, following the architecture of other Rush Stack linting plugins.

Features

  • Runs the oxlint binary through the Heft task system.
  • Supports both:
    • Integration with the TypeScript plugin.
    • Standalone execution without a TypeScript phase.
  • Uses the Heft logger for diagnostics and execution output.
  • Supports incremental linting by leveraging the TypeScript plugin's onChangedFilesHook.
  • Falls back to full-path linting when TypeScript integration is unavailable.
  • Filters files to:
    • Changed files only (incremental mode).
    • Supported source file extensions.
    • Paths outside build output directories.
  • Reports diagnostics through:
    • emitError
    • emitWarning
  • Supports SARIF output generation.
  • Supports passing --fix and other oxlint options through configuration.
  • Uses JSON schema validation for plugin configuration.

Incremental Linting

When incremental: true is enabled and a TypeScript configuration is present, the plugin listens to the TypeScript plugin's changed-files

@github-project-automation github-project-automation Bot moved this to Needs triage in Bug Triage Jul 20, 2026
@yashwanth195 yashwanth195 changed the title heft oxlint plugin [feat: heft-oxlint-plugin]heft oxlint plugin Jul 20, 2026
@yashwanth195 yashwanth195 changed the title [feat: heft-oxlint-plugin]heft oxlint plugin [feat: heft-oxlint-plugin] Add oxlint plugin integration to heft Jul 20, 2026
{
"packageName": "@rushstack/heft-oxlint-plugin",
"comment": "Initial release of a Heft plugin for running oxlint, the fast Rust-based JavaScript/TypeScript linter.",
"type": "none"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Usually the initial release for a newly added plugin should be a minor

const fixArgs: string[] = buildFixArgs(fix, pluginOptions);

// Run oxlint with JSON output so that diagnostics can be parsed and surfaced through the Heft logger.
const jsonArgs: string[] = [...commonArgs, ...fixArgs, '--format=json', ...lintPaths];

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In a large project, is there a risk of this exceeding the maximum CLI length?

Looks like on Linux, not a concern since typically on the order of 2MiB, but Windows only allows 8KiB, so there it could happen for a project with thousands of files.

Probably we should try to contribute to oxlint a --stdin-paths option like Git has, then hand it newline or NUL-delimited filenames via stdin.


this._reportDiagnostics(jsonResult, buildFolderPath, logger);

// If requested, run oxlint a second time to produce a SARIF log file. oxlint can emit SARIF to

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does the SARIF log contain all the data we need? And if so, it seems like it would be more efficient to extract the diagnostics from the SARIF data than to pay the full lint cost a second time.


private async _getOxlintBinPathAsync(buildFolderPath: string, logger: IScopedLogger): Promise<string> {
// Resolve the oxlint package relative to the project being linted, then read its "bin" entry.
const packageJsonPath: string = Import.resolveModule({

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have a standard helper for resolving a package in a riggable package, since we allow the linter to be installed in the rig rather than in the individual package.

private async _spawnOxlintAsync(invocation: IOxlintInvocation): Promise<IWaitForExitResult<string>> {
const { binPath, buildFolderPath, args, logger } = invocation;

// The oxlint "bin" launcher is an ESM Node script, so it must be invoked via Node directly.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In general, our preferred model then would be to bypass the CLI parser and directly feed the config into the oxlint binding, so that we don't have to worry about transporting all the data we need over the command line.

However, it looks like that may cause some complexity around stdout/stderr handling.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The binding's lint() only returns a boolean and writes diagnostics straight to fd 1 (no output-file option), so capturing them in-process needs fragile stdout redirection that clashes with Heft's terminal. Keeping child-process for now.

});
}

private async _runOxlintAsync(

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's start adopting ES2022+ semantics in new code (async #runOxlintAsync() i.e. ECMAScript private class members

This is a Heft plugin to run [oxlint](https://oxc.rs/docs/guide/usage/linter), the fast Rust-based
JavaScript/TypeScript linter from the Oxc project.

Unlike `@rushstack/heft-lint-plugin` (ESLint/TSLint), oxlint does not perform type-aware linting and

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are we not passing the --type-aware CLI option?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Needs triage

Development

Successfully merging this pull request may close these issues.

2 participants